package team.mai.antexpress.dao;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import team.mai.antexpress.entities.PermissionGroupEntity;
import team.mai.antexpress.entities.UserEntity;

import java.io.Serializable;
import java.util.List;

@SuppressWarnings("Duplicates")
@Repository
public class UserDAO {

	@Autowired
	SessionFactory sessionFactory;


	/**
	 * <p>by Inku</p>
	 */
	public UserEntity getUserByUsername(String username) {
		try (Session session = sessionFactory.openSession();) {
			Query query = session.createQuery("FROM UserEntity WHERE username=:username");
			query.setParameter("username", username);
			List list = query.list();
			return list.size() < 1 ? null : (UserEntity) list.get(0);
		} catch (HibernateException e) {
			e.printStackTrace();
			return null;
		}
	}

	public UserEntity getUserById(int id) {
		try (Session session = sessionFactory.openSession();) {
			return session.get(UserEntity.class, id);
		} catch (HibernateException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * by Lief
	 */
	public boolean verifyLogin(String username, String password) {
		try (Session session = sessionFactory.openSession()) {
			Query query = session.createQuery("FROM UserEntity where username=:username and password=:password");
			query.setParameter("username", username);
			query.setParameter("password", password);
			List list = query.list();
			return list.size() >= 1;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}


	private PermissionGroupEntity getPermissionByUser(UserEntity user) {
		try (Session session = sessionFactory.openSession()) {
			Query query = session.createQuery("FROM PermissionGroupEntity WHERE id=:pid");
			query.setParameter("pid", user.getPermissionGroupId());
			List list = query.list();
			if (list.size() < 1)
				return null;
			else {
				return (PermissionGroupEntity) list.get(0);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * receives a user entity and return his permission group entity
	 * by Inku
	 */
	public PermissionGroupEntity getPermissionByUser(int id) {
		UserEntity userById = getUserById(id);
		return getPermissionByUser(userById);
	}

	public PermissionGroupEntity getPermissionByUser(String username) {
		UserEntity userByUsername = getUserByUsername(username);
		return getPermissionByUser(userByUsername);
	}

	/**
	 * @param username
	 * @return the specified user's id, 0 if not found
	 */
	public int getUserIdByUsername(String username) {
		try (Session session = sessionFactory.openSession()) {
			Query<UserEntity> query = session.createQuery("FROM UserEntity WHERE username=:username");
			query.setParameter("username", username);
			List<UserEntity> list = query.list();
			return list.get(0).getId();
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * by Jason
	 */
	public int insert(UserEntity userToInsert) {
		try (Session session = sessionFactory.openSession()) {
			Transaction transaction = session.beginTransaction();
			Serializable save = session.save(userToInsert);
			transaction.commit();
			return (int) save;
		} catch (Exception ex) {
			ex.printStackTrace();
			return -1;
		}
	}

	/**
	 * by Lief
	 */
	public boolean changePassword(String username, String newPassword) {
		try (Session session = sessionFactory.openSession()) {
			Transaction transaction = session.beginTransaction();
			Query query = session.createQuery("FROM UserEntity WHERE username=:username");
			query.setParameter("username", username);
			List list = query.list();
			if (list.size() < 1)
				return false;
			else {
				UserEntity user = (UserEntity) list.get(0);
				user.setPassword(newPassword);
				transaction.commit();
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * by Lief
	 *
	 * @param user
	 * @return
	 */
	public boolean deleteUser(UserEntity user) {
		try (Session session = sessionFactory.openSession()) {
			Transaction transaction = session.beginTransaction();
			session.delete(user);
			transaction.commit();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public boolean deleteUserById(int id) {
		return deleteUser(sessionFactory.openSession().get(UserEntity.class, id));
	}

	public boolean deleteUsersByIds(List<Integer> ids){
		try(Session session = sessionFactory.openSession()){
			Transaction transaction = session.beginTransaction();
			for(int id: ids) {
				UserEntity user = getUserById(id);
				session.delete(user);
			}
			transaction.commit();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * by Lief
	 *
	 * @param user
	 * @return
	 */
	public boolean updateUser(UserEntity user) {
		try (Session session = sessionFactory.openSession()) {
			Transaction transaction = session.beginTransaction();
			session.update(user);
			transaction.commit();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public List<UserEntity> getAllUsers() {
		try (Session session = sessionFactory.openSession()) {
			Query query = session.createQuery("FROM UserEntity ");
			List<UserEntity> list = query.list();
			return list;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	public List<UserEntity> getUsersByTel(String tel) {
		try (Session session = sessionFactory.openSession()) {
			Query query = session.createQuery("FROM UserEntity u where u.mobile like :tel");
			query.setParameter("tel", "%" + tel + "%");
			List<UserEntity> list = query.list();
			return list;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	public List<UserEntity> getUsersByName(String username) {
		try (Session session = sessionFactory.openSession()) {
			Query query = session.createQuery("FROM UserEntity u where u.username like :username");
			query.setParameter("username", "%" + username + "%");
			List<UserEntity> list = query.list();
			return list;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}


}
